<?php

defined('APPLICATION_PATH') 	|| define('APPLICATION_PATH', 	realpath(dirname(__FILE__) . '/../') . '/'	);
defined('LIBRARY_PATH') 		|| define('LIBRARY_PATH', 		APPLICATION_PATH . 'library/'				);
defined('DATA_PATH')	 		|| define('DATA_PATH',  		APPLICATION_PATH . 'data/'					);
defined('LOG_PATH') 			|| define('LOG_PATH', 			APPLICATION_PATH . 'log/'					);
defined('DRIVER_PATH') 			|| define('DRIVER_PATH',		APPLICATION_PATH . 'driver/'				);
defined('CONFIG_PATH') 			|| define('CONFIG_PATH',		APPLICATION_PATH . 'config/'				);

// set include path to the library Path
set_include_path(implode(PATH_SEPARATOR, array(
    LIBRARY_PATH,
    get_include_path(),
)));

require_once 'class.http.php';
require_once 'Zend/Log.php';
require_once 'Zend/Log/Writer/Stream.php';
require_once 'Zend/Config/Ini.php';
//$writer = new Zend_Log_Writer_Stream('/tmp/spiderLog');
//$logger = new Zend_Log($writer);
//$logger->log('Debug message', Zend_Log::DEBUG);
//$logger->log('Info message', Zend_Log::INFO);
//$logger->log('Notice message', Zend_Log::NOTICE);
//$logger->log('Warning message', Zend_Log::WARN);
//$logger->log('Error message', Zend_Log::ERR);
//$logger->log('Critical message', Zend_Log::CRIT);
//$logger->log('Alert message', Zend_Log::ALERT);
//$logger->log('Emergency message', Zend_Log::EMERG);
//exit;

class Grabber extends Http {
	
	/**
	 * All spiders params will be stored here.
	 * 
	 * @var array $config
	 */
	public $config;
	
	/**
	 * In This var will be instantiate the Class.http object.
	 * 
	 * @var object $http
	 */
	public $http;
	
	/**
	 * _init initialize this array with all information keep from line command 
	 * @var array $_aArgv
	 */
	private $_aArgv;
	
	/*
	 * used to set a user agent
	 */
	private $_userAgent;
	
	/*
	 * If true, set the CURL
	 */
	private $_useCurl;
	
	/*
	 * should be GET or POST
	 */
	private $_httpMethod;
	
	/*
	 * if false logPath will be set to defalt /tmp/spider.log
	 */
	
	private $_logPath = false;
	
	protected $logger;

	
	public function __construct($argv = null)
	{
		$this->_init($argv);
		// TODO inserire i parametri giusti al posto di default.
		$this->config = $this->_getConfig(CONFIG_PATH . 'config.ini', 'default');
		var_dump($this->config->spider->url);exit();
		$writer = new Zend_Log_Writer_Stream('/tmp/spider.log');
		$this->logger = new Zend_Log($writer);
		$writer = null;
		if ( ! $this->http = new Http() ){
			$this->logger->log("Could not istantiate Http Class: File. " . __FILE__ . "; Line" . __LINE__ . ";", Zend_Log::EMERG);
		}

	
	}
	
	public function setUserAgent($sUA) {
		$this->_userAgent = $sUA;
	}
	
	public function init(){
		if ( !empty($this->_userAgent) ) {
			$this->http->setUseragent($this->_userAgent);
			$this->logger->log("setUserAgent:" . $this->_userAgent, Zend_Log::DEBUG);
		}
		
		if ( !empty($this->_useCurl) && $this->_useCurl == true ) {
			$this->http->useCurl(true);
		} else {
			$this->http->useCurl(false);
		}
		
		if ( empty($this->_httpMethod) ||  $this->_httpMethod == true || $this->_httpMethod == false ) {
			$this->http->setMethod($this->_httpMethod);
		}
		
		if ( empty($this->_logPath) ) {
		
		}
		
		


		//echo ($this->http->error) ? $this->http->error : $this->http->result;
		//$this->http->result = html_entity_decode($this->http->result);
		/******************************************************************************** */


		
		
	
	}
	
	private function _init($argv) {
		$this->_aArgv['spiderName'] = $argv[1];
		$this->_aArgv['environment'] = (isset($argv[2]) && $argv[2] == 'production') ? 'production' : 'developing';
		
		
		if( count($argv) < 2 ){
			$this->_usage();
		}
		
		if( !$this->_spiderExists() ){
			$this->_usage(1);
		}


		
	}

	/**
	 * Print how to use script
	 */
	private function _usage($code = 0) {
		
		switch($code){
			
			case 1:
				print("\nError - Spider filename doesn't exists.\nCheck your " . DRIVER_PATH . " to the list of avaible spider.\n\n" );
				break;
				
			case 0:	
			default:
				print("\nError -\nUsage: php spider.php SPIDERNAME [production|developing]\n\n\n");
				break;
		}
			
		exit(1);
	}
	
	/**
	 * check if the spider filename exists in the filesystem (return true) or not (return false
	 * @param $argv array
	 * 
	 * @return boolean
	 */
	private function _spiderExists() {
		if( file_exists(DRIVER_PATH . $this->_aArgv['spiderName'] . '.php') ){
			return true;
		}
		return false;
	}
	
	public function query($html, $aQuery) {
	
		$doc = new DOMDocument();
		$doc->loadHTML($html);
		
		$xpath = new DOMXpath($doc);

		foreach ($aQuery as $key => $query) {
			$elements = $xpath->query($query);
			
			if (!is_null($elements)) {
				$i = 0;
				foreach ($elements as $element) {
					$i++;
					$nodes = $element->childNodes;
					foreach ($nodes as $node) {
			      		$array[$i][$key] =  trim($node->nodeValue);
			    	}
			  	}
			}
			
		}
		return $array;
	}
	
	public function saveFase1($aData){

		$dirPath = '/tmp/spider/fase1';
		$numItems = count($aData);
		if($numItems < 1){
			$this->logger->log("Could not save Data count(saveFase1) < 1 ,  File: File. " . __FILE__ . "; Line" . __LINE__ . ";", Zend_Log::EMERG);
			return false;
		}
		
		if( !is_dir($dirPath) ){
			try{
				mkdir($dirPath, 0777, true);
				$this->logger->log("Created dir path $dirPath/ ,  File: File. " . __FILE__ . "; Line" . __LINE__ . ";", Zend_Log::INFO);
			}catch (Exception $e){
				$this->logger->log("Could not create data Directory $dirPath/,  File: File. " . __FILE__ . "; Line" . __LINE__ . ";", Zend_Log::EMERG);
				exit(1);
			}
		}
		
		$chunkStart = 0;
		$chunk = 10;
		$i=0;
		while($chunkStart < $numItems){
			file_put_contents("$dirPath/data_" . ++$i, serialize(array_slice($aData, $chunkStart, $chunk)) );
			$chunkStart += $chunk;
		}
		
	}
	
	/**
	 * Method to find last page of listing fase (fase1()). 
	 * 
	 * @param string $sUrl 				: Url with the parameter to be discovered as last param. example:www.example.com/pc_book.php?pag=
	 * @param string $sQueryNode		: xpath node to the element that differentiate if the page exist or not. (node present = true)
	 * @param string $sQueryValue		: string value expexted from the $sQueryNode xpath.
	 * @param int $iFound				: start value point, the first page is sure present.
	 * @param int $iRange		: 
	 */
	public function guessLastPage($sUrl, $sQueryNode, $sQueryValue, $iFound = 1, $iRange = 1000){
		if( empty($sQueryNode) ){
			$this->logger->log("\$sQueryNode($sQueryNode) must be a xpath node string " . __FILE__ . "; Line" . __LINE__ . ";", Zend_Log::EMERG);
			throw new Exception('$sQueryNode must be a xpath node string');
		}
		$aQuery = array(0 => $sQueryNode);
		
		$this->setUserAgent('Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.9) Gecko/20100401 Ubuntu/9.10 (karmic) Firefox/3.5.9');
		$tidyConfig = array(
			'indent'         					=> true,
			'quote-nbsp'						=> false,
			'output-xhtml'   					=> true,
			'wrap'           					=> 200,
		);
		$iNotFound = null;
		$iTarget = $iRange;
		// test finish when $a =$b but for security purpose, we stop it if $a > $b
		//var_dump(is_null($iNotFound) || $iNotFound - $iFound > 1);
		$i=0;
		while( is_null($iNotFound) || $iNotFound - $iFound > 1){
			$i++;
			$this->http->execute($sUrl . $iTarget);
			$html = tidy_repair_string($this->http->result, $tidyConfig, 'latin1');
			$result = $this->query($html, $aQuery);
			
			if( is_array($result) ){
				list(, $value) = each(array_pop($result));
			} else {
				$value = null;
			}
			
			if( $sQueryValue == $value ){
				$iFound = $iTarget;
				$iTarget = (!is_null($iNotFound)) ? floor( ($iFound + $iNotFound) / 2 ) : $iTarget += $iTarget;
				
			} else {
				$iNotFound = $iTarget;
				$iTarget =  floor( ($iFound + $iNotFound) / 2 ) ;
			}
		}
	$this->logger->log("LastPage guess in $i cycles ,  File: File. " . __FILE__ . "; Line" . __LINE__ . ";", Zend_Log::INFO);
	return (int) $iTarget;	
	}
	
	private function _getConfig($sPath, $sDriver){
		$options['nestSeparator'] = ':';
		$config = new Zend_Config_Ini($sPath, $sDriver);
		return $config;
	}

		
}
